/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package geneontofx.sets;

import geneontofx.association.Association;
import geneontofx.association.AssociationsModel;
import geneontofx.go.OntologyModel;
import geneontofx.go.OntologyTerm;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * @author loskov
 */
public class PopulationSet implements ISet {
    
    private static String DEF_PATH = "src\\_input\\population.txt";
    private static SetType SET_TYPE = SetType.POPULATION;
    
    private String filePath;
    private ArrayList<String> inputList;
    private ConcurrentHashMap<String, ArrayList<Association>> populationAssociationsMap;
    private ConcurrentHashMap<String, ArrayList<OntologyTerm>> populationOntoTermsMap;
    private final ConcurrentHashMap<OntologyTerm, Integer> populationOntoTermsCountMap;
    private Integer populationTotal;
    
    private ArrayList<String> noLinkList;

    public PopulationSet() {
        populationAssociationsMap = new ConcurrentHashMap<>();
        populationOntoTermsMap = new ConcurrentHashMap<>();
        populationOntoTermsCountMap = new ConcurrentHashMap<>();
        noLinkList = new ArrayList<>();
        inputList = new ArrayList<>();
        populationTotal = 0;
    }

    public PopulationSet(String filePath) {
        populationAssociationsMap = new ConcurrentHashMap<>();
        populationOntoTermsMap = new ConcurrentHashMap<>();
        populationOntoTermsCountMap = new ConcurrentHashMap<>();
        noLinkList = new ArrayList<>();
        inputList = new ArrayList<>();
        populationTotal = 0;
        
        this.filePath = filePath;
    }
    

    @Override
    public void setFilePath(String path) {
        this.filePath = path;
    }

    @Override
    public String getFilePath() {
        return filePath;
    }

    @Override
    public void readSetFile(String path) throws FileNotFoundException, IOException{
        if(path == null) path = DEF_PATH;
        FileReader file;
        file = new FileReader(path);
        BufferedReader input = new BufferedReader(file);
        String line;
        while ((line = input.readLine()) != null) {
            inputList.add(line);
        }
        
    }

    @Override
    public void linkAssociations(AssociationsModel associationsInstance) {
        for(String inputLine : inputList) {
            try {
                ArrayList<Association> currAssoc = associationsInstance.getSingleAssociationList(inputLine);
                populationAssociationsMap.put(inputLine, currAssoc);
            }catch(NullPointerException nullPointerEx) {
                noLinkList.add(inputLine);
                //TODO no assoc for input LOGGER
            }
        }
    }

    @Override
    public ConcurrentHashMap<String, ArrayList<Association>> getAssociations() {
        return populationAssociationsMap;
    }

    @Override
    public void linkOntoTerms(OntologyModel ontologyInstance) {
        ConcurrentHashMap<String, OntologyTerm> allOntoTermsMap = ontologyInstance.getOntologyTerms();
        
        for(Map.Entry<String, ArrayList<Association>> entry : populationAssociationsMap.entrySet()) {
            String currKey = (String) entry.getKey();
            ArrayList<Association> currAssocList = (ArrayList<Association>) entry.getValue();
            ArrayList<OntologyTerm> tempOntoTermList = new ArrayList<>();
            for(Association currAssoc : currAssocList) {
                if(allOntoTermsMap.containsKey(currAssoc.getGoId())) {
                    tempOntoTermList.add(allOntoTermsMap.get(currAssoc.getGoId()));
                }
                else System.err.println("No such GOTerm term: " + currAssoc.getGoId()); //TODO LOGGER
            }
            populationOntoTermsMap.put(currKey, tempOntoTermList);
        }
    }

    @Override
    public ConcurrentHashMap<String, ArrayList<OntologyTerm>> getOntoTerms() {
        return populationOntoTermsMap;
    }

    @Override
    public void countOntoTerms() {
        for(Map.Entry<String, ArrayList<OntologyTerm>> entry : populationOntoTermsMap.entrySet()) {
            ArrayList<OntologyTerm> ontoTermsList = entry.getValue();
            for(OntologyTerm currOntoTerm : ontoTermsList) {
                if(populationOntoTermsCountMap.containsKey(currOntoTerm)){
                    Integer currCount = populationOntoTermsCountMap.get(currOntoTerm);
                    populationOntoTermsCountMap.replace(currOntoTerm, currCount+1);
                    populationTotal++;
                }
                else {
                    populationOntoTermsCountMap.put(currOntoTerm, new Integer(1));
                    populationTotal++;
                }
            }
        }
    }

    @Override
    public void clearSet() {
        inputList = null;
        populationAssociationsMap = null;
        populationOntoTermsMap = null;
        filePath = null;
        noLinkList = null;
    }

    @Override
    public ConcurrentHashMap<OntologyTerm, Integer> getCountedOntoTermsMap() {
        return populationOntoTermsCountMap;
    }
    
    public Integer getTotalCount() {
        return populationTotal;
    }
}
